package cn.tedu.mall.front.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.front.service.IFrontCategoryService;
import cn.tedu.mall.pojo.front.entity.FrontCategoryEntity;
import cn.tedu.mall.pojo.front.vo.FrontCategoryTreeVO;
import cn.tedu.mall.pojo.product.vo.CategoryStandardVO;
import cn.tedu.mall.product.service.front.IForFrontCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@DubboService
@Service
@Slf4j
public class FrontCategoryServiceImpl implements IFrontCategoryService {
    //定义redis中的key常量名
    public static final String CATEGORY_TREE_VO = "category_tree";
    //需要调用product模块查询数据库
    @DubboReference
    private IForFrontCategoryService dubboFrontCategoryService;
    //需要将分类信息保存到redis中
    @Autowired
    private RedisTemplate redisTemplate;

    //实现分类信息树结构的呈现
    @Override
    public FrontCategoryTreeVO categoryTree() {
        //定义该方法的返回值类型
        FrontCategoryTreeVO treeVO = null;
        //1.要先查询redis
        if(redisTemplate.hasKey(CATEGORY_TREE_VO)){
          treeVO = (FrontCategoryTreeVO) redisTemplate.boundValueOps(CATEGORY_TREE_VO).get();
        }
        //2.redis中没有查询到分类信息，需要从数据库中查询
        List<CategoryStandardVO> categoryList = dubboFrontCategoryService.getCategoryList();
        //需要将不同级别的分类信息先放到一起
        //分给自己的parent_id
        //我们可以将parentId设置为key值，分类信息是value(List)---Map
        Map<Long,List<FrontCategoryEntity>> map = new HashMap<>();
        //遍历categoryList，先判断是否为null
        if(categoryList==null)
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"分类信息集合为空");
        log.info("当前分类对象总数为：{}",categoryList.size());
        //遍历categoryList集合，进行同父id分类
        for (CategoryStandardVO categoryStandardVO : categoryList) {
            //categoryStandardVO没有children属性，不能保存子分类的
            //所以我需要将categoryStandardVO转成FrontCategoryEntity
            FrontCategoryEntity frontCategoryEntity = new FrontCategoryEntity();
            //利用赋值工具类BeanUtils,进行同名属性赋值
            BeanUtils.copyProperties(categoryStandardVO,frontCategoryEntity);
            //因为后面要反复使用当前对象的父分类id，所以取出来
            Long parentId = frontCategoryEntity.getParentId();
            //要根据parentId向map中存储元素，parentId为key，frontCategoryEntity是value(List)
            if(map.containsKey(parentId)){
                //如果有这个key，我们直接将当前分类对象添加到map的value中
                map.get(parentId).add(frontCategoryEntity);
            }else{
                //如果当前map没有这个key
                //将当前分类对象添加到一个新的List集合中，充当map的value
                List<FrontCategoryEntity> value = new ArrayList<>();
                value.add(frontCategoryEntity);
                //存储到map中
                map.put(parentId,value);
            }
        }
        //通过以上步骤，已经将分类对象存储到map中了，而且已经分好类了
        //我们现在将子分类对象关联到父分类对象的children属性中
        //一级分类对象，我们在数据库中设计的父id为0
        List<FrontCategoryEntity> firstLevels = map.get(0L);
        //判断firstLevels是否为空
        if(firstLevels==null)
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"当前项目没有根分类");
        //遍历一级分类对象集合
        for (FrontCategoryEntity firstLevel : firstLevels) {
            //获取一级分类的id，就是二级分类的父id
            Long secondLevelParentId = firstLevel.getId();
            //获取二级分类集合
            List<FrontCategoryEntity> secondLevels = map.get(secondLevelParentId);
            //判断二级分类集合是否为null
            if(secondLevels==null){
                log.warn("当前分类缺少二级分类内容：{}",secondLevelParentId);
                continue;//结束本次循环进行下一次循环
            }
            //遍历二级分类集合
            for (FrontCategoryEntity secondLevel : secondLevels) {
                //获取当前二级分类的id，是三级分类的父id
                Long thirdLevelParentId = secondLevel.getId();
                //获取三级分类的集合
                List<FrontCategoryEntity> thirdLevels = map.get(thirdLevelParentId);
                //判断三级分类集合是否为null
                if(thirdLevels==null){
                    log.warn("当前分类缺少三级分类内容：{}",thirdLevelParentId);
                    continue;//结束本次循环进行下一次循环
                }
                //将三级分类集合添加到二级分类对象的children属性中
                secondLevel.setChildrens(thirdLevels);
            }
            //将二级分类集合添加到一级分类对象的children属性中
            firstLevel.setChildrens(secondLevels);
        }
        //到此为止所有的分类对象的父子关系都已经构建完成
        //但是本方法返回值类型是FrontCategoryTreeVO
        treeVO = new FrontCategoryTreeVO<>();
        //将一级分类的集合赋值到treeVO中
        treeVO.setCategories(firstLevels);
        //将分好类的分类信息存储到Redis中，以备后续使用
        redisTemplate.boundValueOps(CATEGORY_TREE_VO).set(treeVO);
        //千万记得返回
        return treeVO;
    }
}
